﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GameBaseCode
{
    public class Camera
    {
        public Vector3 pos = new Vector3(0.0f, 0.0f, 0.0f);
	    public float horizontalAng = 0.0f;
        public float verticalAng = 0.0f;
        private Vector3 lookDir = new Vector3(0.0f, 0.0f, -1.0f);
        private Matrix4 modelview = new Matrix4();

        public Camera()
        {
	        
        }
	    public void update(float vx, float vy, float vz, float deltaHang, float deltaVang)
        {
	        horizontalAng += deltaHang;
	        verticalAng += deltaVang;

            Matrix4 rot = Matrix4.ang2Mat(horizontalAng, verticalAng);
        	
	        // Move cam in view direction
            Vector3 moveVector = new Vector3(vx,vy,vz);
            if (Math.Abs(vx) != 0 || Math.Abs(vy) != 0 || Math.Abs(vz) != 0)
            {
                pos += rot.rotate(moveVector); // Move camera
            }

            // Always look forwards
            lookDir.set(0, 0, -1); // -Z is forward in GL
            lookDir = rot.rotate(lookDir);

            if (lookDir.Magnitude <= 0.95)
            {
                throw new Exception("look dir bad");
            }

            Matrix4 tx = new Matrix4(
              1, 0, 0, 0,
              0, 1, 0, 0,
              0, 0, 1, 0,
              -pos.x, -pos.y, -pos.z, 1
            );
            modelview = Matrix4.mul(tx,rot);
        }

        public void setPosition(float px, float py, float pz)
        {
            pos.set(px, py, pz);
        }

        public void setAngle(float hang, float vang)
        {
            this.horizontalAng = hang;
            this.verticalAng = vang;
        }

        public Vector3 getPosition()
        {
            return pos;
        }

        public Vector3 getLookDir()
        {
            return lookDir;
        }


        // http://iphonedevelopment.blogspot.com/2008/12/glulookat.html
        public void lookAt(Vector3 eyePos, Vector3 upward, Vector3 center)
        {
            Vector3 zVec = eyePos - center;
            zVec.normalize();
            Vector3 yVec = upward;
            Vector3 xVec = Vector3.CrossProduct( yVec, zVec );
            yVec = Vector3.CrossProduct( zVec, xVec );
            xVec.normalize();
            yVec.normalize();

            Matrix4 rot = new Matrix4(
                    xVec[0], yVec[0], zVec[0], 0,
                    xVec[1], yVec[1], zVec[1], 0,
                    xVec[2], yVec[2], zVec[2], 0,
                    0,0,0, 1
                    );
            Matrix4 tx = new Matrix4(
              1, 0, 0, 0,
              0, 1, 0, 0,
              0, 0, 1, 0,
             -eyePos[0], -eyePos[1], -eyePos[2], 1
            );
            modelview = Matrix4.mul(tx, rot);

        }

        public float[] getModelview()
        {
            float[] glmatrix = new float[16];
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    glmatrix[i * 4 + j] = modelview.m[i, j];
                }
            }
            return glmatrix;
        }
    }
}
